package utils

import "sync"

type Set struct {
	m map[interface{}]bool
}

func NewSet() *Set {
	return &Set{
		m: map[interface{}]bool{},
	}
}

func (s *Set) Add(item interface{}) {
	s.m[item] = true
}

func (s *Set) Remove(item interface{}) {
	delete(s.m, item)
}

func (s *Set) Has(item interface{}) bool {
	_, ok := s.m[item]
	return ok
}

func (s *Set) Len() int {
	return len(s.m)
}

func (s *Set) Clear() {
	s.m = map[interface{}]bool{}
}

func (s *Set) IsEmpty() bool {
	if s.Len() == 0 {
		return true
	}
	return false
}

func (s *Set) List() []interface{} {
	list := make([]interface{}, 0, len(s.m))
	for item := range s.m {
		list = append(list, item)
	}
	return list
}

type SetSafe struct {
	m  map[interface{}]bool
	mu sync.RWMutex
}

func NewSetSafe() *SetSafe {
	return &SetSafe{
		m:  map[interface{}]bool{},
		mu: sync.RWMutex{},
	}
}

func (s *SetSafe) Add(item interface{}) {
	s.mu.Lock()
	s.m[item] = true
	s.mu.Unlock()
}

func (s *SetSafe) Remove(item interface{}) {
	s.mu.Lock()
	delete(s.m, item)
	s.mu.Unlock()
}

func (s *SetSafe) Has(item interface{}) bool {
	s.mu.RLock()
	_, ok := s.m[item]
	s.mu.RUnlock()
	return ok
}

func (s *SetSafe) Len() int {
	return len(s.m)
}

func (s *SetSafe) Clear() {
	s.mu.Lock()
	s.m = map[interface{}]bool{}
	s.mu.Unlock()
}

func (s *SetSafe) IsEmpty() bool {
	if s.Len() == 0 {
		return true
	}
	return false
}

func (s *SetSafe) List() []interface{} {
	s.mu.RLock()
	list := make([]interface{}, 0, len(s.m))
	for item := range s.m {
		list = append(list, item)
	}
	s.mu.RUnlock()
	return list
}
